class_name BasicEnemy
extends Character


## 进入IDLE状态时，随机待机的时间范围，其中 x 表示最小值，y 表示最大值
@export var idle_random_range: Vector2 = Vector2(0.5, 1.0)

## 死亡时销毁前消失的速度
@export var dissipate_speed: float = 3.0

## 攻击距离（平方值，此为计算距离时进行的优化）
@export var attack_distance: float = 230.0
## 进入攻击状态后到进行攻击之间的准备时间（毫秒），这么做是为了防止检测到能够攻击后给予玩家躲避攻击的机会
@export var duration_pre_punch: int = 500
## 两次攻击之间的间隔时间（毫秒）
@export var duration_between_hits: int = 2000
## 第一段攻击到第二段攻击间的间隔时间（毫秒）
@export var duration_alt_hit: int = 500

## 是否能够重生飞刀
@export var can_respawn_knives: bool
## 重生飞刀的时间间隔（毫秒）
@export var respawn_knife_duration: int

## 进入射击状态后到进行射击的准备时间
@export var duration_pre_shoot: float = 0.6
## 倒地持续时间（秒）
@export var duration_grounded: float = 1.0

## 丢失武器后多长时间后能够进行拾取操作
@export var duration_lost_weapon_pickup: float = 3.0

## 敌人类型，若是由检查点生成的敌人会根据配置的数据修改此类型
@export var enemy_type: EnemyData.EnemyType



const STATE_IDLE := "idle"
const STATE_WALK := "walk"
const STATE_HURT := "hurt"
const STATE_DEATH := "death"
const STATE_FALL := "fall"
const STATE_GROUNDED := "grounded"
const STATE_LAND := "land"
const STATE_FLY := "fly"
const STATE_PUNCH := "punch"
const STATE_THROW := "throw"
const STATE_PICKUP := "pickup"
const STATE_SHOOT := "shoot"
const STATE_DROP := "drop"
const STATE_APPEAR := "appear"


const ANIMATION_IDLE := "idle"
const ANIMATION_WALK := "walk"
const ANIMATION_HURT := "hurt"
const ANIMATION_DEATH := "death"
const ANIMATION_FALL := "fall"
const ANIMATION_GROUNDED := "grounded"
const ANIMATION_LAND := "land"
const ANIMATION_FLY := "fly"
const ANIMATION_PUNCH := "punch"
const ANIMATION_PUNCH_ALT := "punch_alt"
const ANIMATION_THROW := "throw"
const ANIMATION_PICKUP := "pickup"
const ANIMATION_SHOOT := "shoot"
const ANIMATION_DROP := "drop"


## 与玩家目标的距离，为了优化距离计算使用的是平方值
const TARGET_DISTANCE := 20.0
## 远程位置偏移，防止定位到屏幕边缘
const REMOTE_TARGET_OFFSET := 10.0


var player: Player
# 伤害的来源方向，比如攻击源在角色的左侧，则此向量方向为右
var __damage_emit_direction: Vector2
var __last_knife_respawn_time: float = 0.0
var __last_lost_weapon_time: float = 0.0


func _ready():
	super._ready()

	set_initial_node_state()

	damageEmitter.monitoring = false
	damageEmitter.area_entered.connect(on_emit_damage)
	damageReceiver.damage_received.connect(on_receive_damage)

	await get_tree().process_frame
	find_player()


func _process(_delta: float):
	if not enabled:
		return
	process_knife_respawns()


func _can_pickup_weapon() -> bool:
	return not has_knife and not has_gun and not can_respawn_knives and Time.get_ticks_msec() - __last_lost_weapon_time > duration_lost_weapon_pickup


func _can_pickup_food() -> bool:
	return false


# 根据生成数据设置初始化状态
func set_initial_node_state():
	if spawn_entry_mode == Character.EntryMode.DROP:
		stateMachine.spawn_initial_node_state = STATE_DROP
	elif spawn_entry_mode == Character.EntryMode.DOOR:
		stateMachine.spawn_initial_node_state = STATE_APPEAR
		# 从门里生成时，需要设先设置为透明
		modulate = Color.html("#0b111900")


func find_player():
	player = Helper.find_player(get_tree())


# 处理小刀重生
func process_knife_respawns():
	if not can_respawn_knives or has_knife:
		return
	if Time.get_ticks_msec() - __last_knife_respawn_time > respawn_knife_duration:
		__last_knife_respawn_time = Time.get_ticks_msec()
		has_knife = true


# 已投掷小刀
func throws_knife():
	has_knife = false
	__last_knife_respawn_time = Time.get_ticks_msec()
	__last_lost_weapon_time = Time.get_ticks_msec()


# 丢失刀具，需要让小刀掉落到地面
func lost_knife():
	super.lost_knife()
	__last_knife_respawn_time = Time.get_ticks_msec()
	__last_lost_weapon_time = Time.get_ticks_msec()



# 获取远程攻击位置
func get_remote_attack_location() -> Vector2:
	var camera := get_viewport().get_camera_2d()
	var screen_width := get_viewport().get_visible_rect().size.x
	var half_screen_width := screen_width / 2.0

	var left_destination := Vector2(camera.position.x - half_screen_width + REMOTE_TARGET_OFFSET, player.position.y)
	var right_destination := Vector2(camera.position.x + half_screen_width - REMOTE_TARGET_OFFSET, player.position.y)
	if left_destination.distance_squared_to(position) < right_destination.distance_squared_to(position):
		return left_destination
	else:
		return right_destination



## 是否是飞刀攻击模式
func is_flying_knife_attack() -> bool:
	return can_respawn_knives or has_knife

## 是否是射击攻击模式
func is_shoot_gun_attack() -> bool:
	return has_gun



## 看向玩家
func look_at_player():
	look_at_node(player)


## 是否进入近战攻击范围
func is_player_within_attack_range() -> bool:
	if player == null:
		return false
	return global_position.distance_squared_to(player.global_position) < attack_distance



func take_damage_emit_direction() -> Vector2:
	return __damage_emit_direction


# 设置当前生命值
func set_current_health(health: int):
	super.set_current_health(health)
	DamageManager.enemy_health_change.emit(enemy_type, current_health, max_health)



# 发射伤害，子类可重写此方法
func _emit_damage(damage_receiver: DamageReceiver):
	damage_receiver.damage_received.emit(damage, damage_receiver.global_position - damageEmitter.global_position, DamageReceiver.HitType.NORMAL)
	SoundPlayer.play(SoundManager.Sound.HIT1, true)


# 受到伤害，子类可重写此方法
func _receive_damage(damage_value: int, _emit_direction: Vector2, hit: DamageReceiver.HitType):
	# 连击计数
	ComboManager.register_hit.emit()
	# 计算受伤
	set_current_health(current_health - damage_value)
	match hit:
		DamageReceiver.HitType.NORMAL:
			stateMachine.transition_to(STATE_HURT)
		DamageReceiver.HitType.KNOCK_DOWN:
			stateMachine.transition_to(STATE_FALL)
		DamageReceiver.HitType.SHOOT:
			stateMachine.transition_to(STATE_FALL)
		DamageReceiver.HitType.POWER:
			EntityManager.spawn_spark.emit(global_position)
			stateMachine.transition_to(STATE_FLY)



# 发送伤害
func on_emit_damage(receiver_area: Area2D):
	var damage_receiver: DamageReceiver = receiver_area as DamageReceiver
	if damage_receiver == null:
		return
	_emit_damage(damage_receiver)


# 接收到伤害信号
func on_receive_damage(damage_value: int, emit_direction: Vector2, hit: DamageReceiver.HitType):
	__damage_emit_direction = emit_direction

	lost_knife()
	lost_gun()

	_receive_damage(damage_value, emit_direction, hit)
